
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/05/21
// Design Name:
// Module Name: iopmp_control
// Project Name: wujian100
// Target Devices:
// Tool Versions:
// Description:iopmp control FSM
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module iopmp_control(
    input                               iopmpctl_clk_i      ,
    input                               iopmpctl_rst_n_i    ,
    //from sr_reg
    input                               iopmpctl_cfgen_i    ,         
    //from sr_check     
    input                               iopmpctl_hwren_i    ,
    input                               iopmpctl_hrden_i    ,
    input                               iopmpctl_hready_i   ,


    //to sr_check
    output                              iopmpctl_check_en_o ,  
    output[3:0]                         iopmpctl_state_n_o,
    //to sr_reg
    output reg                          iopmpctl_cfgdone_o  
);

localparam IDLE        = 4'b0000;
localparam WRITECMD    = 4'b0001;
localparam WRITEDATA   = 4'b0010;
localparam READCMD     = 4'b0100;
localparam READDATA    = 4'b1000;
// localparam UPDATERULE  = 5'b10000;

reg  [3:0]    state;
reg  [3:0]    state_next;

wire           check_en;
wire           update_en;
wire           update_done;


// // 鐎靛嫬鐡ㄩ弴瀛樻煀娴ｈ儻鍏樻穱鈥冲娇
// always @(posedge iopmpctl_clk_i or negedge iopmpctl_rst_n_i) begin
//     if(!iopmpctl_rst_n_i)
//         update_en <= 1'b0;
//     else if(iopmpctl_cfgen_i == 1'b1)
//         update_en <= 1'b1;
//     else if(state == UPDATERULE)
//         update_en <= 1'b0;
//     else
//         update_en <= update_en;
// end

// // 鐎靛嫬鐡ㄩ弴瀛樻煀鐎瑰本鍨氭穱鈥冲娇
// always @(posedge iopmpctl_clk_i or negedge iopmpctl_rst_n_i) begin
//     if(!iopmpctl_rst_n_i)
//         update_done <= 1'b0;
//     else if(iopmpctl_cfgdone_i == 1'b1)
//         update_done <= 1'b1;
//     else if(state == UPDATERULE)
//         update_done <= 1'b0;
//     else
//         update_en <= update_en;
// end


always @(posedge iopmpctl_clk_i or negedge iopmpctl_rst_n_i) begin
    if(!iopmpctl_rst_n_i)
        state <= 4'd0;
    else
        state <= state_next;
end

always @(*) begin
    case (state)
        IDLE:
          begin
            if(iopmpctl_hwren_i == 1'b1)
                state_next = WRITECMD;
            else if(iopmpctl_hrden_i == 1'b1)  
                state_next = READCMD;
            else
                state_next = IDLE;

          end
        WRITECMD:
          begin
            if(iopmpctl_hwren_i == 1'b1)
                state_next = WRITECMD;
            else if(iopmpctl_hrden_i == 1'b1)
                state_next = READCMD;
            else if(iopmpctl_hready_i == 1'b1)
                state_next = WRITEDATA;
            else
                state_next = WRITECMD;
          end
        READCMD:
          begin
            if(iopmpctl_hwren_i == 1'b1)
                state_next = WRITECMD;
            else if(iopmpctl_hrden_i == 1'b1)
                state_next = READCMD;
            else if(iopmpctl_hready_i == 1'b1)
                state_next = READDATA;
            else
                state_next = READCMD;
          end
        WRITEDATA://鏉╂瑩鍣烽棁锟界憰浣规箒娑擄拷娑擃亝澧︽稉锟介幏宥囨畱鏉╁洨鈻奸崥妤嬬吹閿涚喎娲滄稉铏瑰Ц閹礁褰夐崠鏍ф嫲IDLE娑擄拷閺嶅嚖绱濋幇鐔活潕閸欘垯浜掗崷鈮ADCMD婢跺嫬姘ㄦ潪顒€鍩孖DLE
          begin
            if(iopmpctl_hwren_i == 1'b1)
                state_next = WRITECMD;
            else if(iopmpctl_hrden_i == 1'b1)  
                state_next = READCMD;
            else
                state_next = IDLE;
          end
        READDATA:
          begin 
            if(iopmpctl_hwren_i == 1'b1)
                state_next = WRITECMD;
            else if(iopmpctl_hrden_i == 1'b1)  
                state_next = READCMD;
            else
                state_next = IDLE;
          end
        default: state_next = IDLE;
    endcase
end

assign update_en = ((state == IDLE) & (state_next == IDLE) & (iopmpctl_cfgen_i == 1'b1));
assign iopmpctl_check_en_o = update_en ? 1'b0 : 1'b1;
assign update_done         = update_en ? 1'b1 : 1'b0;
assign iopmpctl_state_n_o     = state_next;

always @(posedge iopmpctl_clk_i or negedge iopmpctl_rst_n_i ) begin
    if(!iopmpctl_rst_n_i) begin
        state              <=  IDLE;
        iopmpctl_cfgdone_o <=  1'b0;
    end
    else begin
       iopmpctl_cfgdone_o  <=  update_done;
       state               <=  state_next;
    end
end

endmodule
